package com.foohoo.benchmark.grammar;

import lombok.extern.slf4j.Slf4j;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * 测试循环中重复定义对性能的影响
 * Benchmark                                                       Mode  Cnt  Score    Error  Units
 * RepeatedCalculationInCycleDef.loopCollectionWithRepeatedCal     avgt    3  5.003 ± 17.967  ns/op
 * RepeatedCalculationInCycleDef.loopCollectionWithoutRepeatedCal  avgt    3  3.280 ±  4.765  ns/op
 * 一句话结论: for的布尔表达式部分会重复计算，造成额外性能损耗，应尝试将循环过程中不会变化的变量放在初始化部分进行计算
 *
 * @author mzdbxqh
 * @date 2020-10-27 09:58
 **/
@Slf4j
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 3, time = 1)
@Fork(1)
@Threads(1)
@State(Scope.Benchmark)
public class RepeatedCalculationInCycleDef {

	private ConcurrentHashMap<Integer, Integer> map = new ConcurrentHashMap<>(INITIAL_SIZE);

	private static final int INITIAL_SIZE = 1024 * 1024;

	private static final int TARGET_SIZE = 1024 * 512;

	@Setup
	public void initialize() {
		for (int i = 0; i < TARGET_SIZE; i++) {
			map.put(i, i);
		}
	}

	@OperationsPerInvocation(TARGET_SIZE)
	@Benchmark
	public void loopCollectionWithRepeatedCal(Blackhole bh) {
		for (int i = 0; i < map.size(); i++) {
			bh.consume(i);
		}
	}

	@OperationsPerInvocation(TARGET_SIZE)
	@Benchmark
	public void loopCollectionWithoutRepeatedCal(Blackhole bh) {
		for (int i = 0, size = map.size(); i < size; i++) {
			bh.consume(i);
		}
	}
}
